#include "statsxx/machine_learning/Ensemble.hpp"


// STL
#include <cmath>  // std::log(), ::exp()
#include <vector> // std::vector<>


//
// DESC: Use a Boost-trained ensemble to evaluate a given input.
//
// NOTE: The ensemble evaluates an input additively:
//
//     F(x) = sum_i f_i(x)
//
//              exp(2*F)
//     p(x) = ------------
//            1 + exp(2*F)
//
// NOTE: ... See the NOTEs below about the factor of 2.
//
// -----
//
// TODO: NOTE: Remember that Boosting (currently) only works for two-class classification.
//
template<typename T>
inline std::vector<double> Ensemble<T>::evaluate_Boost(
                                                       const std::vector<double> &input
                                                       )
{
    std::vector<double> output(1);

    // ADD CLASSIFICATION RULE FOR EACH Learner
    double F = 0.;

    for( auto i = 0; i < this->learners.size(); ++i )
    {
        std::vector<double> output_i = this->learners[i].f_evaluate(input);

        double f_i = 0.5*std::log( (output_i[0]/(1. - output_i[0])) );

        F += f_i;
    }

    // CALCULATE LOGISTIC MODEL

    // NOTE: The usual logistic transform does not have the factor of (1/2) as above (in f_i).
    //
    // NOTE: ... That leads to a factor of 2 in the exponent (below).
    //
    // NOTE: See ::train_Real_AdaBoost() for NOTEs related to this factor.
    //
    // NOTE: ... See also Eq. (15) of Friedman, et al.

    double exp_2F = std::exp( (2*F) );

    output[0] = exp_2F/(1. + exp_2F);

    return output;
}
